﻿using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace MaterialTypeRecognition.Shell.AuthenticationServices
{
    internal class AuthenticationService : IDisposable, IAuthenticationService
    {
        private readonly HttpClient _httpClient;

        public AuthenticationService()
        {
            _httpClient = new HttpClient();
        }

        private string _token = string.Empty;

        public EventHandler? UnauthenticateEvent { get; set; }

        public EventHandler? OPNAuthenticateEvent { get; set; }

        public EventHandler? OPNMonitorAuthenticateEvent { get; set; }

        public EventHandler? MEAuthenticateEvent { get; set; }

        public EventHandler? PEAuthenticateEvent { get; set; }

        public EventHandler? AdminAuthenticateEvent { get; set; }

        public Task UnauthenticateAsync()
        {
            _token = string.Empty;
            UnauthenticateEvent?.Invoke(this, EventArgs.Empty);
            return Task.CompletedTask;
        }

        public bool HasAuthentication => !string.IsNullOrEmpty(_token);

        public async Task<bool> AuthenticateAsync(string password)
        {
            var result = await _httpClient.PostAsync("http://localhost:5323/Authenticate/AuthenticateUser", JsonContent.Create(new AuthenticationModel(password)));
            var jsonResult = await result.Content.ReadFromJsonAsync<AuthenticationResult>();

            if (jsonResult!.IsSuccess)
            {
                _token = jsonResult.Token!;

                if (OPNAuthenticate() || OPNMonitorAuthenticate() || MEAuthenticate() || PEAuthenticate() || AdminAuthenticate())
                {
                    OPNAuthenticateEvent?.Invoke(this, new EventArgs());
                }
                if (OPNMonitorAuthenticate() || MEAuthenticate() || PEAuthenticate() || AdminAuthenticate())
                {
                    OPNMonitorAuthenticateEvent?.Invoke(this, new EventArgs());
                }
                if (MEAuthenticate() || AdminAuthenticate())
                {
                    MEAuthenticateEvent?.Invoke(this, new EventArgs());
                }
                if (PEAuthenticate() || AdminAuthenticate())
                {
                    PEAuthenticateEvent?.Invoke(this, new EventArgs());
                }
                if (AdminAuthenticate())
                {
                    AdminAuthenticateEvent?.Invoke(this, new EventArgs());
                }
            }
            else
            {
                _token = string.Empty;
            }

            return jsonResult!.IsSuccess;
        }

        public bool OPNAuthenticate()
        {
            HttpRequestMessage message = new HttpRequestMessage();
            message.RequestUri = new Uri("http://localhost:5323/Authenticate/OPNAuthenticate");
            message.Method = HttpMethod.Get;

            if (string.IsNullOrWhiteSpace(_token))
            {
                return false;
            }

            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);

            var task = _httpClient.SendAsync(message);
            task.Wait();
            var result = task.Result;

            return result.StatusCode == System.Net.HttpStatusCode.OK;
        }

        public bool OPNMonitorAuthenticate()
        {
            HttpRequestMessage message = new HttpRequestMessage();
            message.RequestUri = new Uri("http://localhost:5323/Authenticate/OPNMonitorAuthenticate");
            message.Method = HttpMethod.Get;

            if (string.IsNullOrWhiteSpace(_token))
            {
                return false;
            }

            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);

            var task = _httpClient.SendAsync(message);
            task.Wait();
            var result = task.Result;

            return result.StatusCode == System.Net.HttpStatusCode.OK;
        }

        public bool MEAuthenticate()
        {
            HttpRequestMessage message = new HttpRequestMessage();
            message.RequestUri = new Uri("http://localhost:5323/Authenticate/MEAuthenticate");
            message.Method = HttpMethod.Get;

            if (string.IsNullOrWhiteSpace(_token))
            {
                return false;
            }

            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);

            var task = _httpClient.SendAsync(message);
            task.Wait();
            var result = task.Result;

            return result.StatusCode == System.Net.HttpStatusCode.OK;
        }

        public bool PEAuthenticate()
        {
            HttpRequestMessage message = new HttpRequestMessage();
            message.RequestUri = new Uri("http://localhost:5323/Authenticate/PEAuthenticate");
            message.Method = HttpMethod.Get;

            if (string.IsNullOrWhiteSpace(_token))
            {
                return false;
            }

            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);

            var task = _httpClient.SendAsync(message);
            task.Wait();
            var result = task.Result;

            return result.StatusCode == System.Net.HttpStatusCode.OK;
        }

        public bool AdminAuthenticate()
        {
            HttpRequestMessage message = new HttpRequestMessage();
            message.RequestUri = new Uri("http://localhost:5323/Authenticate/AdminAuthenticate");
            message.Method = HttpMethod.Get;

            if (string.IsNullOrWhiteSpace(_token))
            {
                return false;
            }

            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);

            var task = _httpClient.SendAsync(message);
            task.Wait();
            var result = task.Result;

            return result.StatusCode == System.Net.HttpStatusCode.OK;
        }

        public void Dispose()
        {
            _httpClient.Dispose();
        }
    }

    class AuthenticationModel
    {
        public string Key { get; set; }

        public AuthenticationModel(string key)
        {
            Key = key;
        }
    }

    class AuthenticationResult
    {
        public bool IsSuccess { get; set; }

        public string? Token { get; set; }
    }
}
